package common.support;

import common.utils.BaseRepositoryImpl;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import java.io.Serializable;

/**
 * @title
 * @description
 * @usage
 * @copyright Copyright 2014  rrmj Corporation. All rights reserved.
 * @company 上海众多美网络科技有限公司
 * @author weseal
 * @create 2018/4/16
 */
public class CustomRepositoryFactoryBean<T extends MongoRepository<S, ID>, S, ID extends Serializable>
		extends MongoRepositoryFactoryBean<T, S, ID> {
	/**
	 * Creates a new {@link MongoRepositoryFactoryBean} for the given repository interface.
	 *
	 * @param repositoryInterface must not be {@literal null}.
	 */
	public CustomRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
		super(repositoryInterface);
	}

	/**
	 * Creates a new {@link MongoRepositoryFactoryBean} for the given repository interface.
	 *
	 * @param operations must not be {@literal null}.
	 */

	@Override
	protected RepositoryFactorySupport getFactoryInstance(MongoOperations operations) {
		return new MyRepositoryFactory(operations);
	}


	private static class MyRepositoryFactory<T, I extends Serializable> extends MongoRepositoryFactory {

		private final MongoOperations mongoOperations;

		public MyRepositoryFactory(MongoOperations mongoOperations) {
			super(mongoOperations);
			this.mongoOperations = mongoOperations;
		}

		@Override
		protected Object getTargetRepository(RepositoryInformation information) {
			Class<?> repositoryInterface = information.getRepositoryInterface();
			MongoEntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
			return new BaseRepositoryImpl<T, I>((MongoEntityInformation<T, I>) entityInformation, this.mongoOperations);
		}

		protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
			return BaseRepositoryImpl.class;
		}

	}
}
